 /*
 * Team Name: Focus
 * Team Members: Diana Groun, Edward Bassan
 * File Name; phase1test.c
 * Description: This file contains the script and tests for the memry, registers and alu
 */

#include<stdio.h>
#include<stdlib.h>
#include"memory.h"
#include"registerFile.h"
#include "alu.h"

// Initializes the register and memory to random numbers
int initiolize(RegFilePtr rf, MemoryPtr mem) {
	printf("Step1:\nBEFORE\nRegisters\n");
	rf->dispalyRegisters(rf);
	printf("Memory\n");
	mem->displayMemory(mem);
	int i;
	for (i = 0; i < REGISTER_FILE_SIZE; i++) {
		rf->setRegister(rf, i, rand());
	}
	for (i = MEMORY_OFFSET; i < MEMORY_OFFSET + MEM_SIZE; i++) {
		mem->storeByte(mem, i, rand());
	}
	printf(
			"Initializing Registers and Memory to random values\nAFTER: \nRegisters\n");
	rf->dispalyRegisters(rf);
	printf("Memory\n");
	mem->displayMemory(mem);
	printf("-------------------------------------------------");
	return 0;
}

// Stores specific values to six registers
int stepThree(RegFilePtr rf) {
	printf("\nBEFORE\n");
	rf->dispalyRegisters(rf);
	printf("STORING 00FF INTO $R6\n");
	rf->setRegister(rf, 6, 0x00ff);
	printf("STORING FFFF INTO $R4\n");
	rf->setRegister(rf, 4, 0xffff);
	printf("STORING ABCD INTO $R2\n");
	rf->setRegister(rf, 2, 0xabcd);
	printf("STORING  0246 INTO $R3\n");
	rf->setRegister(rf, 3, 0x0246);
	printf("STORING 0044 INTO $R5\n");
	rf->setRegister(rf, 5, 0x0044);
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	printf("-----------------------------------------------------");
	return 0;
}

//Stores specific values into memory starting with location 0x3010
int stepFour(RegFilePtr rf, MemoryPtr mem) {
	printf("\nBEFORE\n");
	rf->dispalyRegisters(rf);
	dispalyMemoryLocation(mem, 0x300E, 0x3010 + 8);
	int val[8] = { 0x7F, 0xFF, 0x00, 0x04, 0xFF, 0xA2, 0x05, 0x7A };
	int start = 0x3010;
	int i;
	for (i = 0; i < 8; i++) {
		printf("STORING %.2X AT MEMORY ADRESS %.4X\n", val[i], start);
		mem->storeByte(mem, start, val[i]);
		start++;
	}
	printf("\nAFTER\n");
	rf->dispalyRegisters(rf);
	dispalyMemoryLocation(mem, 0x300E, 0x3010 + 8);
	printf("----------------------------------------------------------");
	return 0;
}

// Stores 2 bytes into a single register
int RegisterFilePack(RegFilePtr reg,int index, Byte hob,Byte lob){
	Word h = 0x0;
	h = hob*256;
	reg->setRegister(reg,index,h);
	//reg->registers[index]->setHob(reg->registers[index],hob);
	reg->registers[index]->setLOB(reg->registers[index],lob);
	return 0;
}

// Stores the values in step three into R1- R4
int stepFive(RegFilePtr rf) {
	printf("\nStep Five\n");
	printf("\nBEFORE\n");
	rf->dispalyRegisters(rf);
	int val[8] = { 0x7F, 0xFF, 0x00, 0x04, 0xFF, 0xA2, 0x05, 0x7A };
	int i;
	int j = 0;
	for (i = 1; i <= 4; i++) {
		RegisterFilePack(rf, i, val[j],val[j + 1]);
		printf("\nSTORING %.2X and %.2X into $R%d\n",val[j],val[j+1],i);
		j = j + 2;
	}
	printf("\nAFTER\n");
		rf->dispalyRegisters(rf);
		printf("----------------------------------------------------------");
		return 0;
}

// Add register 1 and Register 2
int stepSix(RegFilePtr rf){
	printf("\nStep Six\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);
	a->operandA->value = rf->getRegisterValue(rf,1);
	a->operandB->value = rf->getRegisterValue(rf,2);
	a->addition(a);
	rf->setRegister(rf,0,a->resultR->value);
	printf("ADD Registers $R1 and $R2 and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}

// Multiply R4 and R2
int stepSeven(RegFilePtr rf){
	printf("\nStep Seven\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);
	a->operandA->value = rf->getRegisterValue(rf,4);
	a->operandB->value = rf->getRegisterValue(rf,2);
	a->multiplication(a);
	rf->setRegister(rf,0,a->resultR->value);
	printf("MULTIPLY Registers $R4 and $R2 and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}

// Subtract R4 from R3
int stepEight(RegFilePtr rf){
	printf("\nStep Eight\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);
	a->operandA->value = rf->getRegisterValue(rf,3);
	a->operandB->value = rf->getRegisterValue(rf,4);
	a->subtraction(a);
	rf->setRegister(rf,0,a->resultR->value);
	printf("SUBTRACTING Register $R4 from $R3 and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}

// DEVIDING Register $R4 by $R2 and storing ALU.R into  $R0 and remainder in $R8
int stepNine(RegFilePtr rf){
	printf("\nStep Nine\nBEFORE\n");
		rf->dispalyRegisters(rf);
		AluPtr a = aluConstructor();
		a->displayAlu(a);
		a->operandA->value = rf->getRegisterValue(rf,4);
		a->operandB->value = rf->getRegisterValue(rf,2);
		a->division(a,rf->registers[8]);
		rf->setRegister(rf,0,a->resultR->value);
		printf("DEVIDING Register $R4 by $R2 and storing ALU.R into  $R0 and remainder in $R8\n");
		printf("AFTER\n");
		rf->dispalyRegisters(rf);
		a->displayAlu(a);
		printf("----------------------------------------------------------");
		return 0;
}

//XOR Register $R3 and $R4 and storing ALU.R into  $R0
int stepTen(RegFilePtr rf){
	printf("\nStep Ten\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);
	a->operandA->value = rf->getRegisterValue(rf,3);
	a->operandB->value = rf->getRegisterValue(rf,4);
	a->xor(a);
	rf->setRegister(rf,0,a->resultR->value);
	printf("XOR Register $R3 and $R4 and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}
//Shift Left $R3  and storing ALU.R into  $R0
int stepEleven(RegFilePtr rf){
	printf("\nStep Eleven\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);

	a->operandA->value = rf->getRegisterValue(rf,3);
	a->shiftLeft(a);

	rf->setRegister(rf,0,a->resultR->value);
	printf("Shift Left $R3  and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}
//Shift Right $R2 3 times and storing ALU.R into  $R0
int stepTwelve(RegFilePtr rf){
	printf("\nStep Eleven\nBEFORE\n");
	rf->dispalyRegisters(rf);
	AluPtr a = aluConstructor();
	a->displayAlu(a);

	a->operandA->value = rf->getRegisterValue(rf,2);
	a->shiftRight(a);
	a->operandA->value = a->resultR->value;
	a->shiftRight(a);
	a->operandA->value = a->resultR->value;
	a->shiftRight(a);

	rf->setRegister(rf,0,a->resultR->value);
	printf("Shift Right $R2 3 times and storing ALU.R into  $R0\n");
	printf("AFTER\n");
	rf->dispalyRegisters(rf);
	a->displayAlu(a);
	printf("----------------------------------------------------------");
	return 0;
}

// Main method for phase1test
int main() {

	RegFilePtr r = newRegisterFile();
	MemoryPtr mem = newMemory();
	initiolize(r, mem);
	stepThree(r);
	stepFour(r, mem);
	stepFive(r);
	stepSix(r);
	stepSeven(r);
	stepEight(r);
	stepNine(r);
	stepTen(r);
	stepEleven(r);
	stepTwelve(r);
	return 0;
}


